from typing import List, Dict, Union
from Token import Token
from ASTNode import *

# 解析器实现
def parser(tokens: List[Token]) -> ASTNode:
    if not tokens:
        raise ValueError("Nothing to parse. tokens[] is False. Exiting!")
    if len(tokens)==0:
        raise ValueError("Nothing to parse. len(tokens[])==0. Exiting!")

    current = 0

    def advance() -> Token:
        nonlocal current
        current += 1
        return tokens[current]

    def parse_value() -> ASTNode:
        token = tokens[current]
        print("[debug] this token is ", token)
        print("\n")
        token_type = token.get_type()
        if token_type == "String":
            return StringNode(value=token.value)
        elif token_type == "Number":
            return NumberNode(value=float(token.value))
        elif token_type == "True":
            return BooleanNode(value=True)
        elif token_type == "False":
            return BooleanNode(value=False)
        elif token_type == "Null":
            return NullNode()
        elif token_type == "BraceOpen":
            return parse_object()
        elif token_type == "BracketOpen":
            return parse_array()
        else:
            raise ValueError(f"Unexpected token type: {token_type}")

    def parse_object() -> ObjectNode:
        node = ObjectNode(value={})
        token = advance()  # Eat '{'

        while token.get_type() != "BraceClose":
            if token.get_type() == "String":
                key = token.value
                token = advance()  # Eat key
                if token.get_type() != "Colon":
                    raise ValueError("Expected : in key-value pair")
                token = advance()  # Eat ':'
                value = parse_value()  # Recursively parse the value
                node.value[key] = value
            else:
                raise ValueError(f"Expected String key in object. Token type: {token.get_type()}")
            token = advance()  # Eat value or ','
            if token.get_type() == "Comma":
                token = advance()  # Eat ',' if present
        
        return node

    def parse_array() -> ArrayNode:
        node = ArrayNode(value=[])
        token = advance()  # Eat '['

        while token.get_type() != "BracketClose":
            value = parse_value()
            node.value.append(value)

            token = advance()  # Eat value or ','
            if token.get_type() == "Comma":
                token = advance()  # Eat ',' if present
        
        return node

    AST = parse_value()

    return AST
